package com.fit4as.fit
{

import com.fit4as.util.reflect.Field;
import com.fit4as.util.reflect.Method;

import flash.utils.getQualifiedClassName;


    // Copyright (c) 2002 Cunningham & Cunningham, Inc.
    // Released under the terms of the GNU General Public License version 2 or later.


public class TypeAdapter {

    public var target : Object;
    public var fixture : Fixture;
    public var field : Field;
    public var method : Method;
    public var type : Class;


    // Factory //////////////////////////////////

    public static function on( target : Fixture, type : Class ) : TypeAdapter {
        var a : TypeAdapter = adapterFor( type );
        a.init( target, type );
        return a;
    }

    public static function onField( target : Fixture, field : Field ) : TypeAdapter {
    	var type : Class = field.getType();
        var a : TypeAdapter = on( target, type );
        a.target = target;
        a.field = field;
        
        if( a is ArrayAdapter )	ArrayAdapter( a ).componentAdapter = on( target, field.getComponentType());
        return a;
    }

    public static function onMethod( target : Fixture, method : Method ) : TypeAdapter {
    	var type : Class = method.getReturnType();
        var a : TypeAdapter = on( target, type );
        a.target = target;
        a.method = method;
        if( a is ArrayAdapter )	ArrayAdapter( a ).componentAdapter = on( target, method.getComponentType());
        return a;
    }

    public static function adapterFor( type : Class ) : TypeAdapter {
        //t race("TypeAdapter#adapterFor " + type );
        switch( type)
        {
        	case int: return new IntegerAdapter();
        	case Number: return new FloatAdapter();
        	case Boolean: return new BooleanAdapter();
        	case Array: return new ArrayAdapter();
        }
        return new TypeAdapter();
    }


    // Accessors ////////////////////////////////

    protected function init( fixture : Fixture, type : Class ) : void {
        this.fixture = fixture;
        this.type = type;
    }

    public function get() : Object {
        //t race("get " + [ field != null, method != null ]);
        if (field != null) {
            return field.get(target);
        }
        if (method != null) {
            return invoke();
        }
        return null;
    }

    public function set(value : Object) : void {
        field.set(target, value);
    }

    public function invoke() : Object {
        var params : Array = new Array();
        return method.invoke(target, params);
    }

    public function parse(s : String) : Object {
        return fixture.parse( s, type );
    }

    public function equals(a : Object, b : Object) : Boolean {
        //t race("TypeAdapter#equals" + [ typeof a, typeof b, "equals" in a, a == b, a, b ] );
        if( a == null ) return b == null;
        if( "equals" in a ) return a.equals( b );
        return a == b;
    }

    public function toString( o : Object = null ) : String 
    {
        if( o == null ) return getQualifiedClassName( this );
        return o.toString();
    }

}
}

import com.fit4as.fit.TypeAdapter;
import com.fit4as.fit.Fixture;
import mx.utils.StringUtil;
import com.fit4as.util.reflect.ClassUtil;


// Subclasses ///////////////////////////////


class ClassByteAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseInt(s);
    }
}

class ByteAdapter extends ClassByteAdapter {
    override public function set(i : Object) : void {
        field.setByte(target, int(i));
    }
}

class ClassShortAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseInt(s);
    }
}

class ShortAdapter extends ClassShortAdapter {
    override public function set(i : Object) : void {
        field.setShort(target, int(i));
    }
}

class ClassIntegerAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseInt(s);
    }
}

class IntegerAdapter extends ClassIntegerAdapter {
    override public function set(i : Object) : void {
        field.setInt(target, int(i));
    }
}

class ClassLongAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseInt(s);
    }
}

class LongAdapter extends ClassLongAdapter {
    override public function set(i : Object) : void {
        field.setLong(target, int(i));
    }
}

class ClassFloatAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseFloat(s);
    }
}

class FloatAdapter extends ClassFloatAdapter {
    override public function set(i : Object) : void {
        field.setFloat(target, Number(i));
    }
}

class ClassDoubleAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return parseFloat(s);
    }
}

class DoubleAdapter extends ClassDoubleAdapter {
    override public function set(i : Object) : void {
        field.setDouble(target, Number(i));
    }
}

class ClassBooleanAdapter extends TypeAdapter {
    override public function parse(s : String) : Object {
        return s.toLowerCase() == "true";
    }
}

class BooleanAdapter extends ClassBooleanAdapter {
    override public function set(i : Object) : void {
        field.setBoolean(target, i == true);
    }
}

class ArrayAdapter extends TypeAdapter
{
    public var componentAdapter : TypeAdapter;
    
    override public function parse(s : String) : Object
    {
        //t race("ArrayAdapter#parse " + [ s, componentAdapter ]);
        var tokens : Array = s.split(",");
        var result : Array = new Array();
		if( tokens.length == 0 ) return result;
		
	    for( var i : int = 0; i < tokens.length; i++ ){
            //t race("ArrayAdapter#parse " + [ i, tokens[ i ] ]);
            result.push( componentAdapter.parse( StringUtil.trim( tokens[ i ] )));
        }
        return result;
    }

    override public function toString( o : Object = null ) : String {
        if( o == null ) return "";
        var length : int = o.length;

        var result : Array = new Array();
        for( var i : int = 0; i < length; i++ ){
            result.push( componentAdapter.toString( o[ i ] ));
        }
        return result.toString();
    }

    override public function equals( a : Object, b : Object ) : Boolean {
        var length : int = a.length;
        if( length != b.length ) return false;
        
        for( var i : int = 0; i < length; i++ ){
            if( ! componentAdapter.equals( a[i], b[i] )) return false;
        }
        return true;
    }
}